package cn.edu.shou.lab.config.utils;

import cn.edu.shou.lab.config.constant.SHOU;
import org.springframework.util.ResourceUtils;

import java.io.*;
import java.net.URLDecoder;
import java.util.Date;
import java.util.logging.Logger;

/**
 * 文件上传工具类
 */
public class FileUploadUtil {
    private final static Logger LOGGER = Logger.getLogger(FileUploadUtil.class.getName());

    /**
     * 文件上传工具类，检测机制全面
     * @param fileSource 文件输出流
     * @param fileName   保存文件的名字
     * @param ext        文件后缀名
     * @param savePath   文件保存位置的路径
     * @param randomName 是否需要随机新的文件名称
     * @return 新文件路径
     */
    public static String saveFile(InputStream fileSource, String fileName, String ext, String savePath, boolean randomName) {
        //文件输出流为null，异常
        if (fileSource == null) {
            throw new RuntimeException("InputStream [fileSource] can not be null !");
        }
        //fileName和ext不能同时为空
        if((ext == null || ext.isEmpty()) && (fileName == null || fileName.isEmpty())){
            throw new RuntimeException("file name and ext can not be null at the same time !");
        }
        //如果ext不为空，即完善ext格式（后缀名前有.）
        if (ext != null && !ext.isEmpty() && ext.indexOf(".") != 0) {
            ext = "." + ext;
        }
        //如果fileName为空，则ext一定不为空
        if(fileName == null || fileName.isEmpty()){
            fileName = new Date().getTime() + ext;
        }
        //如果ext为空，则fileName一定不为空
        if((ext == null || ext.isEmpty()) && randomName){
            if(fileName.indexOf(".") <= 0){
                ext = "";
            }else {
                ext = fileName.substring(fileName.indexOf("."));
            }
            fileName = new Date().getTime() + ext;
        }

        //保存路径为null，自动上传至默认上传路径；路径未以“/”或“\\”结尾，加上
        if (savePath == null || savePath.isEmpty()) {
            try {
                savePath = ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX + SHOU.UPLOAD_DIRECTORY).getPath().substring(1);
                savePath = URLDecoder.decode(savePath, "utf-8");
            } catch (Exception e) {
                LOGGER.warning(e.getMessage());
                throw new RuntimeException("save path is not specified and default save path initialization error!");
            }
        } else if (!savePath.endsWith("/") && !savePath.endsWith("\\")) {
            if (savePath.contains("/")) {
                savePath += "/";
            } else if (savePath.contains("\\")) {
                savePath += "\\";
            }
        }
        File savePathDir = new File(savePath);
        //如文件上传位置（路径）不存在，则创建
        if (!savePathDir.exists()) {
            if (!savePathDir.mkdirs()) {
                throw new RuntimeException("save path is not available and default save path initialization error!");
            } else {
                LOGGER.info("未找到文件上传路径，已自动创建成功");
            }
        }
        //创建文件
        String newFilePath = (savePath + fileName);
        copy(fileSource, newFilePath);
        return fileName;
    }


    private static void copy(InputStream inputStream, String newFilePath) {
        int n;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            File newFile = new File(newFilePath);
            bis = new BufferedInputStream(inputStream);    //输入流
            bos = new BufferedOutputStream(new FileOutputStream(newFile));    //输出流
            while ((n = bis.read()) != -1) {
                bos.write(n);
            }
        } catch (Exception e) {
            LOGGER.warning("文件输入流 读取/写入 异常");
            LOGGER.warning(e.getMessage());
            throw new RuntimeException("file stream copy error !");
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.warning("文件输入流 关闭 异常");
            }
        }
    }
}
